import { isEmpty } from 'lodash-es';
import { fabric } from 'fabric';

import { getNoAnglePoints, isCroppedLayer } from '../../../utils';
import { getImageBoundByCropped } from '@/utils/fabricJs/cropImage/result';
import {
  handleRectTopMoving,
  handleRectTopScaling
} from '@/utils/fabricJs/cropImage/movement';
import { renderIcon } from '@/utils/fabricJs/cropImage/controls';

export const objectDragChangedProps = [
  'left',
  'top',
  'angle',
  'width',
  'height',
  'scaleX',
  'scaleY'
];

export const imageChangedProps = ['src', ...objectDragChangedProps];

export const cropPathId = 'temp-crop-path';

export const getCropImageObjects = (
  layer: fabric.Image,
  screenSize,
  closeIcon,
  confirmIcon,
  handleCancelCrop,
  handleImageCrop
): any => {
  if (isEmpty(layer)) {
    return layer;
  }

  const [canvasWidth, canvasHeight] = screenSize.split('x').map(Number);
  const { width, height, angle, scaleX, scaleY } = layer;
  const imageWidth = layer.getScaledWidth();
  const imageHeight = layer.getScaledHeight();
  const { center: imageCenterPoint } = getNoAnglePoints(layer);
  const imageCenterTop = imageCenterPoint.y;
  const imageCenterLeft = imageCenterPoint.x;

  const cropPath = new fabric.Rect({
    angle,
    width,
    height,
    scaleX,
    scaleY,
    top: imageCenterTop,
    left: imageCenterLeft,
    opacity: 0.01,
    inverted: true,
    absolutePositioned: true,
    fill: 'rgba(255, 255, 255, 0)',
    cornerSize: 6,
    cornerColor: '#00000080',
    borderColor: '#000',
    cornerStrokeColor: '#000',
    transparentCorners: false,
    strokeWidth: 0,
    strokeUniform: true,
    data: {
      // 用于标识裁剪状态，移动时不显示辅助线
      id: cropPathId
    }
  });

  const mask = new fabric.Rect({
    top: 0,
    left: 0,
    width: canvasWidth * 2,
    height: canvasHeight * 2,
    opacity: 0.5,
    fill: 'rgba(0, 0, 0, 0.75)',
    selectable: false,
    hasControls: false,
    lockMovementX: true,
    lockMovementY: true,
    data: {}
  });

  mask.clipPath = cropPath;

  // 裁剪控制按钮
  cropPath.controls = {
    ...fabric.Object.prototype.controls,
    cancel: new fabric.Control({
      x: 0.5,
      y: 0.5,
      offsetY: 16,
      offsetX: -36,
      cursorStyle: 'pointer',
      mouseUpHandler: handleCancelCrop,
      render: renderIcon(closeIcon),
      sizeX: 24
    }),
    confirm: new fabric.Control({
      x: 0.5,
      y: 0.5,
      offsetY: 16,
      offsetX: -12,
      cursorStyle: 'pointer',
      mouseUpHandler: handleImageCrop,
      render: renderIcon(confirmIcon),
      sizeX: 24
    })
  };

  cropPath.setControlsVisibility({
    mtr: false
  });

  let imageInfo = {
    imageWidth,
    imageHeight,
    scaleX,
    scaleY,
    imageCenterTop,
    imageCenterLeft,
    angle
  };

  const image = layer.data.image;
  if (image.isCropped && isCroppedLayer(image.cropped)) {
    const {
      width: originImageWidth,
      height: originImageHeight,
      left: imageCenterLeft,
      top: imageCenterTop
    } = getImageBoundByCropped(cropPath, image.cropped);
    imageInfo = {
      // 裁剪后要根据原图生成大小和缩放上限
      imageWidth: originImageWidth,
      imageHeight: originImageHeight,
      scaleX: (scaleX * originImageWidth) / imageWidth,
      scaleY: (scaleY * originImageHeight) / imageHeight,
      imageCenterTop,
      imageCenterLeft,
      angle: cropPath.angle
    };
  }

  // 事件处理
  cropPath.on('scaling', function (options) {
    handleRectTopScaling(options, this, imageInfo);
  });

  cropPath.on('moving', function (options) {
    handleRectTopMoving(options, this, imageInfo);
  });

  return { cropPath, mask };
};
